// JORGE FERNANDO GOMEZ
// 1259371
// 189631
// LEC A1
// MARTIN MÜLLER
// D02
// YANG LIU


#include "util.h"
#include "process.h"

#line 13 "process.c"

/* classifyLines() takes a Line * Lines, and tags each line stored according
 * to its first keyword.  Keywords must not have leading whitespace, or
 * classifyLines() will fail.  Returns 0 if successful, or 1 if a line
 * contains bad format. */
int classifyLines ( Line * Lines ) {

    char linebuf[11+1];
    int currentLine = 0;


    while( currentLine < inputFileLength ) {

        sscanf(Lines[currentLine].lineString, " %s", linebuf);

        /* Tag each line depending on keyword found for easier processing. */
        if ( strncmp( linebuf, "#", strlen("#")) == 0 ) {
            Lines[currentLine].commandType = COMMENT;
        }
        else if ( strncmp( linebuf, "Figure",
                    strlen("Figure")) == 0 ) {
            Lines[currentLine].commandType = FIGURE;
        }
        else if ( strncmp( linebuf, "End",
                    strlen("End")) == 0 ) {
            Lines[currentLine].commandType = END;
        }
        else if ( strncmp( linebuf, "drawFigure",
                    strlen("drawFigure")) == 0 ) {
            Lines[currentLine].commandType = DRAWFIGURE;
        }
        else if ( strncmp( linebuf, "draw",
                    strlen("draw")) == 0 ) {
            Lines[currentLine].commandType = DRAW;
        }
        else if ( strncmp( linebuf, "printFigure",
                    strlen("printFigure")) == 0 ) {
            Lines[currentLine].commandType = PRINTFIGURE;
        }
        else if ( strncmp( linebuf, "translate",
                    strlen("translate")) == 0 ) {
            Lines[currentLine].commandType = TRANSLATE;
        }
        else if ( strncmp( linebuf, "child",
                    strlen("child")) == 0 ) {
            Lines[currentLine].commandType = CHILD;
        }
        else
            return 1;

        currentLine++;
    }

    return 0;
}

/* getFigureSpecs() takes a Line * Lines, and checks for a tag FIGURES
 * inside each line.  When a tag is found, properties about the figure
 * defined at that line are stored in FigStack * Figures. */
void getFigureSpecs (Line * Lines, FigStack * Figures, int currentLine ) {

    /* Local string buffers. */
    char tempbuf[6+1];
    char localFigName[MAXLEN_FIG+1];

    int figIndex;   /* Holds index for previously defined figure. */

    /* Look for up to permitted boundaries. */
    if ( currentLine < inputFileLength-2 ) {

        sscanf(Lines[currentLine].lineString, " %s%s",
                tempbuf, localFigName);


        /* Check whether a figure figexists or not. If it does not exist and
         * we haven't gone past our figure limit, store it.  If it does
         * exist, then it's being redifined, so clearfig it and updatefig it.
         * In both cases we look for draw commands (if any). */
        if ( !(figexists(localFigName, Figures)) ) {

            addFig(Figures, localFigName);
            updatefig( Lines[currentLine].lineString,
                    Figures, Figures->figureCount, 2);

            currentLine++;

            while ( Lines[currentLine].commandType != END &&
                    currentLine < inputFileLength-2 ) {

                if ( Lines[currentLine].commandType == DRAW )

                    updatefig( Lines[currentLine].lineString,
                            Figures, Figures->figureCount, 1);

                currentLine++;
            }

            Figures->figureCount++; /* Keep track of figures defined and stored. */
        }
        else if ( figexists(localFigName, Figures) ) {

            /* Get index of a previously defined figure. */
            figIndex = getFigIndex(localFigName, Figures);

            updatefig(Lines[currentLine].lineString, Figures, figIndex, 2);
            clearfig(Figures, figIndex, 0);
            currentLine++;

            while ( Lines[currentLine].commandType != END &&
                    currentLine < inputFileLength-2 ) {

                if ( Lines[currentLine].commandType == DRAW )

                    updatefig( Lines[currentLine].lineString,
                            Figures, figIndex, 1);

                currentLine++;
            }
        }
    }
}

/* executeCommands() goes through each line in Lines and checks for their tag.
 * Depending on each tag, an different action is taken. */
void executeCommands ( FILE * outputFile, Line * Lines, FigStack Figures ) {

    char tempbuf[11+1];
    char figureName[MAXLEN_FIG+1];

    int figIndex = 0;
    int currentLine = 0;

    double tx, ty;      /* Deltas (x, y). */

    /* Go through each line, and do something depending on the keyword. */
    for ( currentLine = 0; currentLine < inputFileLength; currentLine++ ) {

        switch ( Lines[currentLine].commandType ) {

            case FIGURE:
                getFigureSpecs(Lines, &Figures, currentLine);
                break;

            case TRANSLATE:
            case PRINTFIGURE:
            case DRAWFIGURE:

                sscanf(Lines[currentLine].lineString, "%s%s%lf%lf",
                        tempbuf, figureName, &tx, &ty);
                figIndex = getFigIndex(figureName, &Figures);

                if ( Lines[currentLine].commandType == TRANSLATE )
                    translateFigure(&Figures, figIndex, tx, ty);
                else
                    drawPrintFigure(outputFile, &Figures, figIndex,
                            Lines[currentLine].commandType);

                break;

            case COMMENT:
                printf("%s\n", Lines[currentLine].lineString);
                break;

            case CHILD:
                sendChildCommands(outputFile, Lines, currentLine);
                break;

            default:
                break;
        }
    }
}


/* drawPrintFigure() takes a FigStack * Figures the definition stored
 * in index.  Commands are piped to outputFile or printed to stdout
 * depending on type. */
void drawPrintFigure( FILE * outputFile, FigStack * Figures,
                      int figIndex, int type) {

    int drawCount;
    long x, y;          /* Current (x, y) pen position. */
    long dx, dy;        /* Deltas (x, y) for current pen position. */
    long xNew, yNew;    /* New (x, y) pen position after deltas are applied. */

    /* Retrieve data. */
    drawCount = Figures->figProperties[figIndex].drawCount;
    x = lround( Figures->figProperties[figIndex].x );
    y = lround( Figures->figProperties[figIndex].y );

    /* Carry out appropiate actions depending on command type. */
    if (type == PRINTFIGURE) {
        printf("Print Figure %s =\n",
                Figures->figProperties[figIndex].figureName);

        /* Do not print anything if there were no draw commands. */
        if ( Figures->figProperties[figIndex].drawCount )
            printf("%ld %ld\n", x, y);

    }

    int i;  /* Repeat up to the amount of draw commands found. */
    for (i = 0; i < drawCount; i++) {

        /* Retrieve deltas (x, y). */
        dx = lround( Figures->figProperties[figIndex].dx[i] );
        dy = lround( Figures->figProperties[figIndex].dy[i] );
        xNew = x + dx;
        yNew = y + dy;

        /* Carry out appropriate action according to specification. */
        if (type == PRINTFIGURE)
            printf("%ld %ld\n", xNew, yNew);
        else
            fprintf(outputFile, "drawSegment %ld %ld %ld %ld\n",
                    x, y, xNew, yNew);

        x = xNew;
        y = yNew;
    }

    if (type == PRINTFIGURE)
        printf("End Figure %s\n",
                Figures->figProperties[figIndex].figureName);

}

/* translateFigure() transforms FigStack * Figures at index by adding the
 * deltas (tx, ty) to the current stored (x, y) values. */
void translateFigure ( FigStack * Figures, int figIndex,
                       double tx, double ty) {

    /* Add (tx, ty) to current (x, y). */
    Figures->figProperties[figIndex].x += tx;
    Figures->figProperties[figIndex].y += ty;

}

/* sendChildCommands() pipes to outputFile commands following the "child"
 * keyword up to the end of the string found in Line * Lines at lineNumber. */
void sendChildCommands (FILE * outputFile, Line * Lines, int currentLine) {

    char * childCommands;

    int strLength = strlen(Lines[currentLine].lineString);

    /* Get substring of commands which should follow child. */
    childCommands = substr(Lines[currentLine].lineString, 5, strLength-5);

    /* Send substring of commands to Sketchpad.jar. */
    fprintf(outputFile, "%s\n", childCommands);

    free(childCommands);

}

